/**
 *
 *
 */
var SocialDashboard = new function() {

/**
 *
 */
var Dashboard = function(config, container) { 
  var dashboard = this;

  dashboard.el = $('<div class="dashboard"></div>')
    .appendTo(container)
    .height($(document).height())
    .data('dashboard', this)

  var gadgetConfs = config.gadgets || [];
  $.each(config.gadgets || [], function(i, gdconfig) {
    new Gadget(gdconfig, dashboard)
  });
}

Dashboard.prototype = {
  /**
   *
   */
  addGadget : function(gdconfig) {
    new Gadget(gdconfig, this);
  }
  ,

  /**
   *
   */
  save : function() {
    var gadgets = [];
    $('.floating-gadget').each(function() {

    })
    return this;
  }
  ,

  /**
   *
   */
  dirty : function(dirty) { 
    if (typeof dirty !== 'undefined') {
      this._dirty = dirty; 
      return this;
    } else {
      return this._dirty;
    }
  }
}


/**
 *
 *
 */
var Gadget = function(config, dashboard) { 
  var gadget = this;
  this.initConfig = config;

  var id = 'floating-gadget-'+(Gadget.count++);
  gadget.el = $('<div class="floating-gadget" id="'+id+'"></div>')
    .append($('<div class="main" />')
      .append('<div class="tl"><div class="tr"><div class="tc"></div></div></div>')
      .append('<div class="ml"><div class="mr"><div class="mc"></div></div></div>')
      .append('<div class="bl"><div class="br"><div class="bc"></div></div></div>'))
    .width(config.w || 250)
    .css({ 
      position : 'absolute',
      opacity : .1,
      zIndex : Gadget.zIndex++,
      left : config.x || Math.floor(($(document).width() - (config.w || 250)) / 2),
      top : config.y || Math.floor(($(document).height() - (config.h || 150)) / 2)
    })
    .appendTo(dashboard.el)
    .draggable({ containment : '.dashboard' })
    .resizable({ 
      minWidth : 150,
      minHeight : 100,
      handles : 'se', 
      alsoResize : '#'+id+' .mc' 
    })
    .mousedown(function() { gadget.focus() })
    .bind('dragstop', function() { dashboard.dirty(true) })
    .bind('resizestop', function() { dashboard.dirty(true) })
    .data('gadget', this)

  if (config.url) {
    $('<div class="gadget-body"></div>')
      .appendTo(gadget.el.find('.mc'))
      .gadget(config.url, { skin : { CONTENT_BG_COLOR : '#ffffff' } })
  } else if (config.html) {
    $('<div class="gadget-body"></div>')
      .appendTo(gadget.el.find('.mc'))
      .html(config.html)
  }
  if (config.title) {
    $('<div class="header">')
      .appendTo(gadget.el.find('.tc'))
      .html(config.title)
  }
  if (config.h) {
    gadget.el.height(config.h);
  }
  if (config.closable !== false) {
    $('<div class="btn-close"></div>')
      .mouseover(function() { $(this).animate({ opacity : .9 }) })
      .mouseout(function() { $(this).animate({ opacity : .01 }) })
      .click(function() {
        dashboard.dirty(true);
        gadget.el.fadeOut('slow', function() { $(this).remove() });
      })
      .appendTo(gadget.el)
      .css({ opacity : .01 });
  }

  gadget.el.animate({ opacity : .9 }, { duration : 1000, complete : function() {
    gadget.focus();
  }})
}

Gadget.count = 0;
Gadget.zIndex = 1000;

Gadget.prototype = {
  /**
   *
   */
  focus : function() {
    var gadget = this;
    var id = gadget.el.attr('id');
    $('.floating-gadget').each(function() {
      var gd = $(this);
      if (gd.attr('id')===id) {
        gd.css({ opacity : 1, zIndex : Gadget.zIndex++ });
      } else {
        gd.css({ opacity : .8 });
      }
    })
  }
  ,

  /**
   *
   */
  config : function() {
    var offset = this.el.offset();
    var config = $.extend({}, this.initConfig);
    return $.extend(config, {
      x : offset.left, y : offset.top,
      w : this.el.width()
    });
  }
}

/**
 *
 */
var GadgetBar = function(gadgets, container) { 
  var gbar = this;
  gbar.gadgets = gadgets;
  gbar.el = $('<div class="gadget-bar"></div>')
    .append(
      $('<div class="buttons"><div class="btn-toggle"></div></div>')
        .click(function() {
          gbar.el.find('.main').slideToggle();
          $(this).toggleClass('open');
        })
    )
    .append(
      $('<div class="main"></div>')
        .append($('<div class="gadget-list"></div>'))
        .hide()
    )
    .appendTo(container)

  var gdlist = gbar.el.find('.gadget-list');

  gdlist.append('<div class="separator"></div>')
        .append(
          $('<div class="gadget new-gadget"></div>')
            .append($('<div class="title"></div>').text(GadgetBar.LABEL_LOAD_NEW_GADGET))
            .append($('<div class="icon"></div>'))
            .click(function() { gbar.showNewGadgetDialog() })
        )

  for (var url in gadgets) {
    var gdconfig = $.extend({ url : url }, gadgets[url]);
    this.addGadget(gdconfig);
  }

}


GadgetBar.LABEL_LOAD_NEW_GADGET = 'Load Gadget';

GadgetBar.prototype = {
  /**
   *
   */
  registerDashboard : function(dashboard) {
    this.dashboard = dashboard;
  }
  ,

  /**
   *
   */
  showNewGadgetDialog : function() {
    var url = prompt('input new gadget URL', '')
    if (/^https?:\/\//.test(url)) {
      this.loadGadget(url);
    }
  }
  ,

  /**
   *
   */
  loadGadget : function(url) {
    console.log('loading... : '+url);
    var gbar = this;

    $.ajax({
      url : url,
      dataType : 'xml',
      success : parseGadgetXML
    })

    function parseGadgetXML(doc) {
      var modulePref = doc.getElementsByTagName('ModulePrefs')[0]
      var gdconfig = gbar.gadgets[url] = { 
        title : modulePref.getAttribute('title'),
        description : modulePref.getAttribute('description'),
        userPrefs : getUserPrefs(doc)
      };
      gbar.addGadget($.extend({ url : url }, gdconfig));
    }

    function getUserPrefs(doc) {
      var ret = [];
      var userPrefs = doc.getElementsByTagName('UserPref');
      for (var i=0, len=userPrefs.length; i<len; i++) {
        var el = userPrefs[i];
        var userPref = {
          name : el.getAttribute('name'),
          displayName : el.getAttribute('display_name'),
          dataType : el.getAttribute('datatype'),
          required : el.getAttribute('required')==='true',
          defaultValue : el.getAttribute('default_value')
        }
        if (userPref.dataType=='enum') {
          userPref.enumValues = [];
          var enums = el.getElementsByTagName('EnumValue');
          for (var j=0; j<enums.length; j++) {
            userPref.enumValues.push({
              value : enums[j].getAttribute('value'),
              displayValue : enums[j].getAttribute('display_value')
            });
          }
        }
        ret.push(userPref);
      }
      return ret;
    }
  }
  ,

  /**
   *
   */
  addGadget : function(gdconfig) {
    var gbar = this;
    var separator = this.el.find('.gadget-list .separator');
    var gadget = $('<div class="gadget"></div>')
      .append($('<div class="title"></div>').text(gdconfig.title))
      .append($('<div class="icon"></div>'))
      .data('config', gdconfig)
      .insertBefore('.gadget-list .separator')
      .click(function() { gbar.dashboard.addGadget($(this).data('config')) })
    if (gdconfig.icon) {
      gadget.find('.icon').css('backgroundImage', gdconfig.icon);
    }
  }

}

/**
 *
 */
return {

  Dashboard : Dashboard,
  GadgUet : Gadget,
  GadgetBar : GadgetBar,

  DEFAULT_GADGETS : {
    'http://www.google.com/friendconnect/gadgets/members.xml' : {
      title : 'メンバー'
    },
    'http://www.google.com/friendconnect/gadgets/wall.xml' : {
      title : 'コメント'
    },
    'http://bijint.com/bijint.xml' : {
      title : '美人時計'
    },
    'http://yamashita.appspot.com/static/beauty.xml' : {
      title : 'チャンネー'
    }
  },

  /**
   *
   */
  init : function() {
    this.render({ 
      gbar : {
        gadgets : {} 
      },
      dashboard : {
        'default' : {

        }
      }
    })
  }
  ,

  /**
   *
   */
  render : function(config) {
    var gadgets = $.extend({}, this.DEFAULT_GADGETS);
    gadgets = $.extend(gadgets, config.gbar.gadgets);
    var gbar = new GadgetBar(gadgets , document.body);
    var dashboard = new Dashboard(config.dashboard['default'], document.body);
    gbar.registerDashboard(dashboard);
  }

}

}
